#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from playwright.sync_api._generated import Locator,FrameLocator
from pathlib import Path
from dragon.selector import Selector
from dragon.should import LocatorShould
import allure
import logging
from typing import Literal

class DraLocator:
    def __init__(self,locator:Locator|FrameLocator,se:Selector ,draPage):
        from dragon.page import DraPage
        self._se = se
        self.draPage:DraPage=draPage
        self._locator=locator

###### method ######
    def locator(self, se:Selector):
        # DraLocator(self._locator.selector(se.selector), se, self.draPage).wait_for()
        return DraLocator(self._locator.locator(se.selector), se, self.draPage)

    def filter(self,hasText:str=None,hasNotText:str=None,has=None,hasNot=None):
        locator=self._locator.filter(has_text=hasText,has_not_text=hasNotText,has=has._locator if has else None,has_not=hasNot._locator if hasNot else None)
        return DraLocator(locator,self._se,self.draPage)

    def wait_for(self,state:Literal["attached", "detached", "hidden", "visible"]='visible'):
        self._locator.last.wait_for(state=state)

    def all(self) -> list:
        # return list(map(lambda selector:DraLocator(selector,self._se,self.draPage),self._locator.all()))
        return self._locator.all()

    def check(self):
        stepText = f'步骤：定位到【{self._se.name}({self.text})】>> 并勾选'
        with allure.step(stepText):
            logging.info(stepText)
            self._locator.check()
        return self

    def uncheck(self):
        stepText = f'步骤：定位到【{self._se.name}({self.text})】>> 并取消勾选'
        with allure.step(stepText):
            logging.info(stepText)
            self._locator.uncheck()
        return self

    def clear(self,force:bool=False):
        stepText = f'步骤：定位到【{self._se.name}】>> 并清空输入'
        with allure.step(stepText):
            logging.info(stepText)
            self._locator.clear(force=force)
        return self

    def fill(self, text):
        stepText = f'步骤：定位到【{self._se.name}】>> 并输入【{text}】'
        with allure.step(stepText):
            logging.info(stepText)
            self._locator.fill(text)
        return self

    def press(self,key:str,delay:int=0):
        stepText = f'步骤：定位到【{self._se.name}】>> 并按【{key}】键'
        with allure.step(stepText):
            logging.info(stepText)
            self._locator.press(key=key,delay=delay)
        return self

    def press_sequentially(self,text,delay:int=0):
        stepText = f'步骤：定位到【{self._se.name}({self.text})】>> 并依次按【{"、".join(text)}】'
        with allure.step(stepText):
            logging.info(stepText)
            self._locator.press_sequentially(text=text,delay=delay)
        return self

    def click(self,force:bool=False,delay=0):
        stepText = f'步骤：定位到【{self._se.name}({self.text})】>> 并单击'
        with allure.step(stepText):
            logging.info(stepText)
            self._locator.click(force=force,delay=delay)
        return self.draPage

    def tap(self,force:bool=False):
        stepText = f'步骤：定位到【{self._se.name}({self.text})】>> 并轻触'
        with allure.step(stepText):
            logging.info(stepText)
            self._locator.tap(force=force)
        return self.draPage

    def focus(self):
        '''定位到元素并聚焦'''
        stepText = f'步骤：定位到【{self._se.name}】>> 并聚焦'
        with allure.step(stepText):
            logging.info(stepText)
            self._locator.focus()
        return self

    def hover(self,force:bool=False):
        '''定位到元素并悬停'''
        stepText = f'步骤：定位到【{self._se.name}】>> 并悬停'
        with allure.step(stepText):
            logging.info(stepText)
            self._locator.hover(force=force)
        return self

    def right_click(self,force:bool=False,delay=0):
        stepText = f'步骤：定位到【{self._se.name}({self.text})】>> 并右击'
        with allure.step(stepText):
            logging.info(stepText)
            self._locator.click(force=force,delay=delay)

    def dblclick(self,force:bool=False,delay=0):
        stepText = f'步骤：定位到【{self._se.name}({self.text})】>> 并双击'
        with allure.step(stepText):
            logging.info(stepText)
            self._locator.dblclick(force=force,delay=delay)
        return self.dblclick(force=force,delay=delay)

    def scroll_into_view(self):
        '''查找元素并滚动到元素可见'''
        stepText = f'步骤：定位到【{self._se.name}】>> 并滚动到可见'
        with allure.step(stepText):
            logging.info(stepText)
            self._locator.scroll_into_view_if_needed()
        return self

    def drag_to_locator(self, draLocator):
        stepText = f'步骤：定位到【{self._se.name}】>> 并拖拽到【{draLocator._se.name}({draLocator.text})】'
        with allure.step(stepText):
            logging.info(stepText)
            self._locator.drag_to(draLocator._locator)
        return self.draPage

    def select_text(self,force:bool=False):
        stepText = f'步骤：定位到【{self._se.name}】>> 并选中文本内容'
        with allure.step(stepText):
            logging.info(stepText)
            self._locator.select_text(force=force)
        return self.draPage

    def highlight(self):
        self._locator.highlight()
        return self

    def blur(self):
        self._locator.blur()
        return self

    def upload(self, files:list[str|Path]|str|Path):
        '''上传文件，要绝对路径'''
        stepText = f'步骤：定位到【{self._se.name}】>> 上传文件【{files}】'
        with allure.step(stepText):
            logging.info(stepText)
            self._locator.set_input_files(files)

    def screenshot(self, fileName:str|Path):
        '''元素截图'''
        self._locator.screenshot(path=fileName)

    def get_attribute(self, name: str):
        '''获取元素指定属性值'''
        return self._locator.get_attribute(name)

    def nth(self,index:int):
        if index>=0:
            name=f'第{index+1}个'+self._se.name
        else:
            name= f'倒数第{-index}个' + self._se.name
        se = Selector(self._se.selector, name)
        return DraLocator(self._locator.nth(index), se, self.draPage)

    def all_text(self) -> list:
        return self._locator.all_text_contents()

    def should(self):
        return LocatorShould(self)

###### method end ######

###### bool ######
    def is_checked(self) -> bool:
        '''检查checkbox是否被选中'''
        return self._locator.is_checked()

    def is_visible(self) -> bool:
        '''检查元素是否可见'''
        return self._locator.is_visible()

    def is_hidden(self) -> bool:
        return self._locator.is_hidden()

    def is_editable(self) -> bool:
        return self._locator.is_editable()

    def is_disabled(self) -> bool:
        return self._locator.is_disabled()

    def is_enabled(self) -> bool:
        '''检查元素是否可用'''
        return self._locator.is_enabled()

    def is_empty(self) -> bool:
        return not bool(self.count())

    def is_not_empty(self) -> bool:
        return bool(self.count())

    def count(self) -> int:
        return self._locator.count()

###### bool end ######

###### property ######
    @property
    def text(self):
        '''获取元素文本'''
        text = self._locator.text_content()
        return text

    @property
    def html(self):
        return self._locator.inner_html()

    @property
    def location(self):
        '''元素左上角相对于父级元素的位置'''
        stepText = f'步骤：定位到【{self._se.name}】>> 并拖并获取位置信息'
        with allure.step(stepText):
            logging.info(stepText)
            return self._locator.bounding_box()

    @property
    def first(self):
        se=Selector(self._se.selector, '第1个' + self._se.name)
        return DraLocator(self._locator.first, se,self.draPage)

    @property
    def last(self):
        se = Selector(self._se.selector, '最后1个' + self._se.name)
        return DraLocator(self._locator.last, se,self.draPage)

class DraFrameLocator(DraLocator):
    pass




